package name.panitz.ludens.strategy;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import name.panitz.ludens.util.Pair;
class MuehleBoard extends Box{
  private Muehle game;
  int SIZE = 2;
  int UNIT=50;

  GameAI<Move> ai = new AlphaBetaGame<Move>(){
    @Override  int getDepth(){
      if(game.movesDone<=6)return 6;
      if(game.movesDone<=14)return 7;
      return 8;
    }
  };

  int getWidthHeight(){return Math.min(board.getWidth(),board.getHeight());}
  int getUnit(){return getWidthHeight()/7;}

  final OuterTiles outerOne = new OuterTiles((byte)9,Color.RED);
  final OuterTiles outerTwo = new OuterTiles((byte)9,Color.BLUE);

  final OuterTiles removedOne = new OuterTiles((byte)0,Color.RED);
  final OuterTiles removedTwo = new OuterTiles((byte)0,Color.BLUE);

  final Board board=new Board();

  final JButton nextMove=new JButton("nextMove");
  final JButton undoMove=new JButton("undoMove");
  final JLabel  movesDoneL=new JLabel("0");
  
  @Override
  public Dimension getPreferredSize(){
    return new Dimension(500,400);
  }

  Pair<Integer,Integer> positionToGui(Position p){
    int x=(p.pos<3)?p.pos:((p.pos<5)?2:((p.pos==5)?1:0));
    int y=(p.pos<3)?0:((p.pos>3&&p.pos<7)?2:1);
    int start=getUnit()/2+(2-p.triblet)*getUnit();
    int factor=(p.triblet+1)*getUnit();
    return new Pair<Integer,Integer>(start+factor*x,start+factor*y);
  }

  MuehleBoard(Muehle g){
    super(BoxLayout.Y_AXIS);
    this.game=g;

    Box gameBox = new Box( BoxLayout.X_AXIS);
    Box left = new Box( BoxLayout.X_AXIS);
    left.add(outerOne);
    left.add(removedTwo);

    Box right = new Box( BoxLayout.X_AXIS);
    right.add(outerTwo);
    right.add(removedOne);

    gameBox.add(right);
    gameBox.add(board);
    gameBox.add(left);

    JPanel buttons = new JPanel();

    buttons.add(undoMove);
    buttons.add(nextMove);
    buttons.add(movesDoneL);

    add(gameBox);
    add(buttons);

    undoMove.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent ev){
        if (game.prevState!=null) setGame(game.prevState);
      }
    });
    nextMove.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent ev){
	setGame((Muehle)ai.doBestMove(game));
      }
    });

    System.out.println("OK");
  }

  void setGame(Muehle game){
    this.game=game;
    movesDoneL.setText(""+game.movesDone);
    outerOne.setNumber(game.playerStartStones[Muehle.ONE%2]);
    outerTwo.setNumber(game.playerStartStones[Muehle.TWO%2]);
    removedOne.setNumber((byte)(9-game.playerStones[Muehle.ONE%2]));
    removedTwo.setNumber((byte)(9-game.playerStones[Muehle.TWO%2]));
    repaint();
  }

  class OuterTiles extends JPanel{
    private byte number;
    private final Color color;
    OuterTiles(byte number,Color color){
	this.number=number;
	this.color=color;
    }

    void setNumber(byte number){
	this.number=number;
    }

    @Override
    public Dimension getPreferredSize(){
      return new Dimension(getUnit()/2,getUnit()*9/2);
    }

    @Override
    public void paintComponent(Graphics g){
	setBackground(Color.GREEN);
      super.paintComponent(g);
      g.setColor(color);
      for (byte i=(byte)0;i<number;i++){
        g.fillOval(0,i*getUnit()/2,getUnit()/2,getUnit()/2);
      }
    }
  }

  class Board extends JPanel{
    Position boardToPosition(Point xy){
      final double x = xy.getX();
      final double y = xy.getY();
      
      final byte TOP=(byte)0;
      final byte BOTTOM=(byte)1;
      final byte LEFT=(byte)2;
      final byte RIGHT=(byte)3;
      byte sq= -1;
      byte tblr=-1;
      if      (y<getUnit())                 {sq=2;tblr=TOP;}
      else if (y>6*getUnit()&&y<7*getUnit()){sq=2;tblr=BOTTOM;}
      else if (x<getUnit())                 {sq=2;tblr=LEFT;}
      else if (x>6*getUnit()&&x<7*getUnit()){sq = 2;tblr=RIGHT;}


      else if (y>1*getUnit()&&y<2*getUnit()){sq=1;tblr=TOP;}
      else if (y>5*getUnit()&&y<6*getUnit()){sq=1;tblr=BOTTOM;}
      else if (x>1*getUnit()&&x<2*getUnit()){sq=1;tblr=LEFT;}
      else if (x>5*getUnit()&&x<6*getUnit()){sq=1;tblr=RIGHT;}

      else if (y>2*getUnit()&&y<3*getUnit()){sq=0;tblr=TOP;}
      else if (y>4*getUnit()&&y<5*getUnit()){sq=0;tblr=BOTTOM;}
      else if (x>2*getUnit()&&x<3*getUnit()){sq=0;tblr=LEFT;}
      else if (x>4*getUnit()&&x<5*getUnit()){sq=0;tblr=RIGHT;}

	  
      if (sq==-1)return null;

      if ((tblr==TOP||tblr==BOTTOM)){
        if ((2-sq+1)*getUnit()>x)
          return new Position(sq,(byte)((tblr==TOP)?0:6));
	if ((4+sq)*getUnit()<x) 
          return new Position(sq,(byte)((tblr==TOP)?2:4));
	if (3*getUnit()<x&&4*getUnit()>x)
          return new Position(sq,(byte)((tblr==TOP)?1:5));
      }
      if (3*getUnit()<y&&4*getUnit()>y)
        return new Position(sq,(byte)((tblr==LEFT)?7:3));
      return null;
    }
    Board(){
      addMouseListener(new MouseAdapter(){
         Position marked = null;
         boolean removing=false;
	 public void mouseClicked(MouseEvent ev){
           final Position pos = boardToPosition(ev.getPoint());
           System.out.println(pos);
	   if (pos==null) return;
	   if (!removing){
             if (game.movesDone<18){
	       setGame(game.doMove(new Set(pos)));
	       if (game.inMuehle(pos)) removing=true;
             }else{
		 if (marked==null)marked=pos;
		 else {
		   setGame(game.doMove(new MoveStone(marked,pos)));
		   marked=null;
		   if (game.inMuehle(pos)) removing=true;
		 }
	     }

	   }else{
             new RemoveStone(pos).move(game);
             removing=false;
             setGame(game);
           }
	 }
      });
    }

    @Override
    public void paintComponent(Graphics g){
      super.paintComponent(g);
      paintBoard(g);
      paintStones(g);
    }

    @Override
    public Dimension getPreferredSize(){
      return new Dimension(300,300);
    }

    void setColor(byte pl,Graphics g){
      switch (pl) {
        case Muehle.ONE: g.setColor(Color.RED);break;
        case Muehle.TWO: g.setColor(Color.BLUE);break;
      }
    }

    void  paintStone(Graphics g,Position p){
      final Pair<Integer,Integer> pos=positionToGui(p);
      g.fillOval(pos.fst-getUnit()/2/2
                ,pos.snd-getUnit()/2/2
                ,getUnit()/2
                ,getUnit()/2);
    }

    void paintStones(Graphics g){
      for (byte c=0;c<MuehleBoard.this.game.columns;c++){
        for (byte r=0;r<MuehleBoard.this.game.rows;r++){
          if (game.b[c][r]!=Muehle.NONE){
            setColor(game.b[c][r],g);
            paintStone(g,new Position(c,r));
          }
        }
      }      
    }

    void paintBoard(Graphics g){
      g.fillRect(getUnit()/2-SIZE,getUnit()/2-SIZE
                ,6*getUnit()+SIZE,SIZE);
      g.fillRect(getUnit()/2-SIZE,6*getUnit()+getUnit()/2-SIZE
                ,6*getUnit()+SIZE,SIZE);

      g.fillRect(getUnit()/2-SIZE,getUnit()/2-SIZE
                ,SIZE,6*getUnit()+SIZE);
      g.fillRect(6*getUnit()+getUnit()/2-SIZE,getUnit()/2-SIZE
                ,SIZE,6*getUnit()+SIZE);

      g.fillRect(getUnit()/2-SIZE+getUnit(),getUnit()+getUnit()/2-SIZE
                ,4*getUnit()+SIZE,SIZE);
      g.fillRect(getUnit()/2-SIZE+getUnit(),5*getUnit()+getUnit()/2-SIZE
                ,4*getUnit()+SIZE,SIZE);

      g.fillRect(getUnit()/2-SIZE+getUnit(),getUnit()+getUnit()/2-SIZE
                ,SIZE,4*getUnit()+SIZE);
      g.fillRect(4*getUnit()+getUnit()/2-SIZE+getUnit(),getUnit()+getUnit()/2-SIZE
                ,SIZE,4*getUnit()+SIZE);

      g.fillRect(getUnit()/2-SIZE+2*getUnit(),2*getUnit()+getUnit()/2-SIZE
                ,2*getUnit()+SIZE,SIZE);
      g.fillRect(getUnit()/2-SIZE+2*getUnit(),4*getUnit()+getUnit()/2-SIZE
                ,2*getUnit()+SIZE,SIZE);

      g.fillRect(getUnit()/2-SIZE+2*getUnit(),2*getUnit()+getUnit()/2-SIZE
                ,SIZE,2*getUnit()+SIZE);
      g.fillRect(2*getUnit()+getUnit()/2-SIZE+2*getUnit(),2*getUnit()+getUnit()/2-SIZE
                ,SIZE,2*getUnit()+SIZE);


      g.fillRect(getUnit()/2-SIZE+3*getUnit(),getUnit()/2-SIZE
                ,SIZE,2*getUnit()+SIZE);
      g.fillRect(getUnit()/2-SIZE+3*getUnit(),4*getUnit()+getUnit()/2-SIZE
                ,SIZE,2*getUnit()+SIZE);

      g.fillRect(getUnit()/2-SIZE,getUnit()/2-SIZE+3*getUnit()
                ,2*getUnit()+SIZE,SIZE);
      g.fillRect(4*getUnit()+getUnit()/2-SIZE,getUnit()/2-SIZE+3*getUnit()
                ,2*getUnit()+SIZE,SIZE);
    }
  }
  public static void main(String[] args)throws Exception{
    Muehle v = new Muehle();
    MuehleBoard mb = new MuehleBoard(v); 
    JFrame f = new JFrame();

    f.add(mb);

    f.pack();
    f.setVisible(true);
    System.out.println("fertig");
  }
}

